home *** CD-ROM | disk | FTP | other *** search
/ Kit PC World De Ampliacion De Windows 95 / Kit PC World de ampliacion de Windows 95.iso / internet / sweeper / samples / asyncstg / bytearr.cpp < prev    next >
C/C++ Source or Header  |  1995-12-05  |  18KB  |  790 lines

  1. #include "barrobj.h"
  2.  
  3. #include <windows.h>
  4. #include "connect.h"
  5.  
  6. CAsyncByteArray::CAsyncByteArray()
  7. {
  8.     m_dwRefCount=0;
  9.     m_punkInner=NULL;
  10.     m_punkOuter=NULL;
  11.  
  12.     m_bTerminated=FALSE;
  13.     m_bBlocking=TRUE;
  14.  
  15.     InitializeCriticalSection(&m_sectNewReadAllowed);
  16.     m_nReadsPending=0;
  17.     m_hevntNoReadsPending=NULL;
  18.  
  19.     m_hevntNewFillInfo=NULL;
  20.     m_nFillAlloc=0;
  21.     m_nFillInfo=0;
  22.     m_pFillInfo=NULL;
  23.     m_ulFillSize=0;
  24.  
  25.     InitializeCriticalSection(&m_sectLBConnect);
  26.     m_pCacheArray=NULL;
  27.     m_pDataArray=NULL;
  28.     m_pLBConnect=NULL;
  29. }
  30.  
  31. HRESULT CAsyncByteArray::Initialize(IUnknown* punkOuter) {
  32.     try
  33.     {
  34.         m_punkInner=new CInnerUnk(this);
  35.     }
  36.     catch(...)
  37.     {
  38.         m_punkInner=NULL;
  39.         return E_OUTOFMEMORY;
  40.     }
  41.  
  42.     if (punkOuter) 
  43.     {
  44.         m_punkOuter=punkOuter;
  45.     }
  46.     else
  47.     {
  48.         m_punkOuter=(IUnknown*) m_punkInner;
  49.     }
  50.  
  51.     m_hevntNoReadsPending=CreateEvent(NULL, TRUE, TRUE, NULL);
  52.     if (!m_hevntNoReadsPending)
  53.     {
  54.         return E_UNEXPECTED;
  55.     }
  56.     m_hevntNewFillInfo=CreateEvent(NULL, TRUE, FALSE, NULL);
  57.     if (!m_hevntNewFillInfo)
  58.     {
  59.         CloseHandle(m_hevntNoReadsPending);
  60.         m_hevntNoReadsPending=NULL;
  61.         return E_UNEXPECTED;
  62.     }
  63.     m_pFillInfo=(FILLINFO*) GlobalAlloc(GPTR, sizeof(FILLINFO)*FILLINFOINITSIZE);
  64.     if (!m_pFillInfo)
  65.     {
  66.         CloseHandle(m_hevntNoReadsPending);
  67.         m_hevntNoReadsPending=NULL;
  68.         CloseHandle(m_hevntNewFillInfo);
  69.         m_hevntNewFillInfo=NULL;
  70.         return E_OUTOFMEMORY;
  71.     }
  72.     m_nFillAlloc=FILLINFOINITSIZE;
  73.     m_nFillInfo=0;
  74.     return S_OK;
  75. }
  76.  
  77. CAsyncByteArray::~CAsyncByteArray() 
  78. {
  79.     if (m_pFillInfo) 
  80.     {
  81.         WRITEFILLINFOLOCK;
  82.         m_nFillInfo=0;
  83.         m_nFillAlloc=0;
  84.         GlobalFree((HGLOBAL)m_pFillInfo);
  85.         m_pFillInfo=NULL;
  86.         WRITEFILLINFOUNLOCK;
  87.     }
  88.  
  89.     if (m_hevntNewFillInfo)
  90.     {
  91.         CloseHandle(m_hevntNewFillInfo);
  92.         m_hevntNewFillInfo=NULL;
  93.     }
  94.  
  95.     if (m_hevntNoReadsPending)
  96.     {
  97.         CloseHandle(m_hevntNoReadsPending);
  98.         m_hevntNoReadsPending=NULL;
  99.     }
  100.     if (m_pCacheArray) 
  101.     {
  102.         ILockBytes *pLB=m_pCacheArray;
  103.         m_pCacheArray=NULL;
  104.         pLB->Release();
  105.     }
  106.     if (m_pDataArray) 
  107.     {
  108.         ILockBytes *pLB=m_pDataArray;
  109.         m_pDataArray=NULL;
  110.         pLB->Release();
  111.     }
  112.     if (m_pLBConnect) 
  113.     {
  114.         CoDisconnectObject((IUnknown*) m_pLBConnect, NULL);
  115.         if (m_pLBConnect)
  116.         {
  117.             delete m_pLBConnect;
  118.             m_pLBConnect=NULL;
  119.         }
  120.     }
  121.     DeleteCriticalSection(&m_sectLBConnect);
  122.     DeleteCriticalSection(&m_sectNewReadAllowed);
  123.     if (m_punkInner)
  124.     {
  125.         delete m_punkInner;
  126.     }
  127. }
  128.  
  129. HRESULT CAsyncByteArray::QueryInterface(REFIID riid, void** ppObject) {
  130.     if (IsBadWritePtr(this, sizeof(*this))) 
  131.     {
  132.         return E_POINTER;
  133.     }
  134.     return m_punkOuter->QueryInterface(riid, ppObject);
  135. }
  136.  
  137. ULONG CAsyncByteArray::AddRef() 
  138. {
  139.     if (IsBadWritePtr(this, sizeof(*this))) 
  140.     {
  141.         return E_POINTER;
  142.     }
  143.     return m_punkOuter->AddRef();
  144. }
  145.  
  146. ULONG CAsyncByteArray::Release()
  147. {
  148.     if (IsBadWritePtr(this, sizeof(*this))) 
  149.     {
  150.         return E_POINTER;
  151.     }
  152.     return m_punkOuter->Release();
  153. }
  154.  
  155. CAsyncByteArray::CInnerUnk::CInnerUnk(CAsyncByteArray* pObj)
  156. {
  157.     m_pObj=pObj;
  158. }
  159.  
  160. HRESULT CAsyncByteArray::CInnerUnk::QueryInterface(REFIID riid, void** ppObject) 
  161. {
  162.     if (IsBadWritePtr(this, sizeof(*this))) 
  163.     {
  164.         return E_POINTER;
  165.     }
  166.     if (riid==IID_IUnknown || riid==IID_ILockBytes) 
  167.     {
  168.         *ppObject=(ILockBytes*) m_pObj;
  169.     }
  170.     else if (riid==IID_IFillLockBytes) 
  171.     {
  172.         *ppObject=(IFillLockBytes*) m_pObj;
  173.     }
  174.     else if (riid==IID_IConnectionPointContainer) 
  175.     {
  176.         *ppObject=(IConnectionPointContainer*) m_pObj;
  177.     }
  178.     else 
  179.     {
  180.         return E_NOINTERFACE;
  181.     }
  182.     m_pObj->AddRef();
  183.     return S_OK;
  184. }
  185.  
  186. ULONG CAsyncByteArray::CInnerUnk::AddRef() 
  187. {
  188.     if (IsBadWritePtr(this, sizeof(*this))) 
  189.     {
  190.         return E_POINTER;
  191.     }
  192.     InterlockedIncrement((long*) &g_dwRefCount);
  193.     InterlockedIncrement((long*) &m_pObj->m_dwRefCount);
  194.     return m_pObj->m_dwRefCount;
  195. }
  196.  
  197. ULONG CAsyncByteArray::CInnerUnk::Release()
  198. {
  199.     if (IsBadWritePtr(this, sizeof(*this))) 
  200.     {
  201.         return E_POINTER;
  202.     }
  203.     ULONG dwRefCount=(m_pObj->m_dwRefCount)-1;
  204.     InterlockedDecrement((long*) &g_dwRefCount);
  205.     if (InterlockedDecrement((long*) &m_pObj->m_dwRefCount)==0) 
  206.     {
  207.         delete m_pObj;
  208.         return 0;
  209.     }
  210.     return dwRefCount;
  211. }
  212.  
  213. HRESULT CAsyncByteArray::ReadAt(ULARGE_INTEGER ulOffset,void *pv, ULONG cb, ULONG *pcbRead) 
  214. {
  215.     if (IsBadWritePtr(this, sizeof(*this))) 
  216.     {
  217.         return E_POINTER;
  218.     }
  219.     if (!m_pCacheArray)
  220.     {
  221.         return ASTG_E_NOTINITIALIZED;
  222.     }
  223.  
  224.     if (pcbRead)
  225.     {
  226.         *pcbRead=0;
  227.     }
  228.     DWORD dwIndex=0;
  229.     FILLINFO* pFillInfo=NULL;
  230.     DWORDLONG ulEnd=ulOffset.QuadPart+cb;
  231.     do 
  232.     {
  233.         READFILLINFOLOCK;
  234.         while (dwIndex<m_nFillInfo)
  235.         {
  236.             pFillInfo=m_pFillInfo+dwIndex;
  237.             if (ulOffset.QuadPart>=pFillInfo->ulOffset)
  238.             {
  239.                 if (ulEnd<=pFillInfo->ulOffset+pFillInfo->cb)
  240.                 {
  241.                     // All data is here
  242.                     READFILLINFOUNLOCK;
  243.                     return m_pCacheArray->ReadAt(ulOffset, pv, cb, pcbRead);
  244.                 }
  245.                 // Part of the data is here: try to read the rest from the Data Array
  246.                 DWORD cbAvailable=(DWORD) (pFillInfo->cb-(pFillInfo->ulOffset-ulOffset.QuadPart));
  247.                 ULARGE_INTEGER ulFirstNonAvailable;
  248.                 ulFirstNonAvailable.QuadPart=ulOffset.QuadPart+cbAvailable;
  249.                 // (cast DWORDLONG to DWORD is safe since cbAvailable<=cb per the preceding conditions)
  250.                 if (m_bBlocking)
  251.                 {
  252.                     if (m_pDataArray)
  253.                     {
  254.                         DWORD cbDataRead=0;
  255.                         m_pDataArray->ReadAt(ulFirstNonAvailable, ((BYTE*) pv)+cbAvailable, cb-cbAvailable, &cbDataRead);
  256.                         if (cbDataRead>0)
  257.                         {
  258.                             FillAt(ulFirstNonAvailable, ((BYTE*) pv)+cbAvailable, cbDataRead, NULL);
  259.                             if (cbDataRead==cb-cbAvailable)
  260.                             {
  261.                                 cbDataRead=0;
  262.                                 HRESULT hRes=m_pCacheArray->ReadAt(ulOffset, pv, cbAvailable, &cbDataRead);
  263.                                 if (cbDataRead==cbAvailable)
  264.                                 {
  265.                                     if (pcbRead)
  266.                                     {
  267.                                         *pcbRead=cb;
  268.                                     }
  269.                                     return hRes;
  270.                                 }
  271.                             }
  272.                         }
  273.                     }
  274.                     break; // for now we retry everything 
  275.                     // This could be optimized by reading the available part now and obtain just the rest later
  276.                 }
  277.                 else
  278.                 {
  279.                     READFILLINFOUNLOCK;
  280.                     // Read from cache
  281.                     DWORD cbCacheRead=0;
  282.                     HRESULT hRes=m_pCacheArray->ReadAt(ulOffset, pv, cbAvailable, &cbCacheRead);
  283.                     if (pcbRead)
  284.                     {
  285.                         *pcbRead=cbCacheRead;
  286.                     }
  287.                     // Try to read the missing part from the Data Array
  288.                     if (cbCacheRead==cbAvailable && m_pDataArray)
  289.                     {
  290.                         DWORD cbDataRead=0;
  291.                         hRes=m_pDataArray->ReadAt(ulFirstNonAvailable, ((BYTE*) pv)+cbAvailable, cb-cbAvailable, &cbDataRead);
  292.                         if (cbDataRead>0)
  293.                         {
  294.                             if (pcbRead)
  295.                             {
  296.                                 *pcbRead+=cbDataRead;
  297.                             }
  298.                             FillAt(ulFirstNonAvailable, ((BYTE*) pv)+cbAvailable, cbDataRead, NULL);
  299.                         }
  300.                         if (cbCacheRead+cbDataRead<cb)
  301.                         {
  302.                             hRes= ((m_bTerminated || 
  303.                                     (m_ulFillSize && ulEnd>m_ulFillSize)) ? E_FAIL : ASTG_E_PENDING);
  304.                         }
  305.                     }
  306.                     return hRes;
  307.                 }
  308.             }
  309.             dwIndex++; // not this block
  310.         };
  311.         READFILLINFOUNLOCK;
  312.         if (m_bBlocking)
  313.         {
  314.             if (m_ulFillSize && ulEnd>m_ulFillSize)
  315.             {
  316.                 return E_FAIL;
  317.             }
  318.             DWORD res=WaitForSingleObject(m_hevntNewFillInfo, INFINITE); // wait until the next call to FillAt/FillAppend/FillSetSize/Terminate
  319.             if (WAIT_FAILED==res)
  320.             {
  321.                 return E_UNEXPECTED;
  322.             }
  323.             if (WAIT_ABANDONED==res)
  324.             {
  325.                 return E_FAIL;
  326.             }
  327.         }
  328.         else
  329.         {
  330.             if (pcbRead)
  331.             {
  332.                 *pcbRead=0;
  333.             }
  334.             return (m_bTerminated ? E_FAIL : ASTG_E_PENDING);
  335.         }
  336.     }
  337.     while (!m_bTerminated);
  338.     return E_FAIL;
  339. }
  340.  
  341. HRESULT CAsyncByteArray::WriteAt(ULARGE_INTEGER ulOffset,const void *pv, ULONG cb, ULONG *pcbWritten) 
  342. {
  343.     if (IsBadWritePtr(this, sizeof(*this))) 
  344.     {
  345.         return E_POINTER;
  346.     }
  347.     if (m_pDataArray)
  348.     {
  349.         m_pDataArray->WriteAt(ulOffset, pv, cb, pcbWritten);
  350.     }
  351.  
  352.     return FillAt(ulOffset, pv, cb, pcbWritten);
  353. }
  354.  
  355. HRESULT CAsyncByteArray::Flush( void) 
  356. {
  357.     if (IsBadWritePtr(this, sizeof(*this))) 
  358.     {
  359.         return E_POINTER;
  360.     }
  361.     if (m_pDataArray)
  362.     {
  363.         m_pDataArray->Flush();
  364.     }
  365.     if (m_pCacheArray)
  366.     {
  367.         return m_pCacheArray->Flush();
  368.     }
  369.     return S_OK;
  370. }
  371.  
  372. HRESULT CAsyncByteArray::SetSize(ULARGE_INTEGER cb) 
  373. {
  374.     if (IsBadWritePtr(this, sizeof(*this))) 
  375.     {
  376.         return E_POINTER;
  377.     }
  378.     if (m_pDataArray)
  379.     {
  380.         m_pDataArray->SetSize(cb);
  381.     }
  382.     return SetFillSize(cb);
  383. }
  384.  
  385. HRESULT CAsyncByteArray::LockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) 
  386. {
  387.     if (IsBadWritePtr(this, sizeof(*this))) 
  388.     {
  389.         return E_POINTER;
  390.     }
  391.     if (!m_pCacheArray)
  392.     {
  393.         return ASTG_E_NOTINITIALIZED;
  394.     }
  395.  
  396.     if (m_pDataArray)
  397.     {
  398.         m_pDataArray->LockRegion(libOffset, cb, dwLockType);
  399.     }
  400.     
  401.     return m_pCacheArray->LockRegion(libOffset, cb, dwLockType);
  402. }
  403.  
  404. HRESULT CAsyncByteArray::UnlockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) 
  405. {
  406.     if (IsBadWritePtr(this, sizeof(*this))) 
  407.     {
  408.         return E_POINTER;
  409.     }
  410.     if (!m_pCacheArray)
  411.     {
  412.         return ASTG_E_NOTINITIALIZED;
  413.     }
  414.  
  415.     if (m_pDataArray)
  416.     {
  417.         m_pDataArray->UnlockRegion(libOffset, cb, dwLockType);
  418.     }
  419.     
  420.     return m_pCacheArray->UnlockRegion(libOffset, cb, dwLockType);
  421. }
  422.  
  423. HRESULT CAsyncByteArray::Stat(STATSTG *pstatstg, DWORD grfStatFlag) {
  424.     if (IsBadWritePtr(this, sizeof(*this))) 
  425.     {
  426.         return E_POINTER;
  427.     }
  428.  
  429.     if (!m_pCacheArray)
  430.     {
  431.         return ASTG_E_NOTINITIALIZED;
  432.     }
  433.     return m_pCacheArray->Stat(pstatstg, grfStatFlag);
  434. }
  435.  
  436.     
  437. // IFillLockBytes methods
  438. HRESULT CAsyncByteArray::SetFillSize(ULARGE_INTEGER cb) {
  439.     if (IsBadWritePtr(this, sizeof(*this))) 
  440.     {
  441.         return E_POINTER;
  442.     }
  443.     if (!m_pCacheArray) 
  444.     {
  445.         return ASTG_E_NOTINITIALIZED;
  446.     }
  447.     HRESULT hRes=m_pCacheArray->SetSize(cb);
  448.     if (FAILED(hRes)) 
  449.     {
  450.         return hRes;
  451.     }
  452.     WRITEFILLINFOLOCK;
  453.     m_ulFillSize=cb.QuadPart;
  454.     DWORD dwIndex=0;
  455.     FILLINFO* pFillInfo=NULL;
  456.     while (dwIndex<m_nFillInfo)
  457.     {
  458.         pFillInfo=m_pFillInfo+dwIndex;
  459.         // is this block outside the new size?
  460.         if (pFillInfo->ulOffset>=cb.QuadPart) 
  461.         {
  462.             m_nFillInfo=dwIndex; // invalidate it and all the following!
  463.             break;
  464.         }
  465.         // is part of this block outsize the new size?
  466.         if (pFillInfo->ulOffset+pFillInfo->cb>cb.QuadPart)
  467.         {
  468.             pFillInfo->cb=cb.QuadPart-pFillInfo->ulOffset; // truncate it
  469.             m_nFillInfo=dwIndex+1; // remove all the following blocks
  470.             break;
  471.         }
  472.         dwIndex++;
  473.     }
  474.     WRITEFILLINFOUNLOCK;
  475.     PulseEvent(m_hevntNewFillInfo);
  476.     return hRes;
  477. }
  478.  
  479. HRESULT CAsyncByteArray::FillAppend(void const *pv, ULONG cb, ULONG *pcbWritten) 
  480. {
  481.     if (IsBadWritePtr(this, sizeof(*this))) 
  482.     {
  483.         return E_POINTER;
  484.     }
  485.     if (!m_pCacheArray) 
  486.     {
  487.         return ASTG_E_NOTINITIALIZED;
  488.     }
  489.     
  490.     WRITEFILLINFOLOCK; // for now: suboptimal since it disables reading while appending!
  491.     DWORDLONG ulEnd;
  492.     FILLINFO* pFillInfo=NULL;
  493.     if (m_nFillInfo>0)
  494.     {
  495.         pFillInfo=m_pFillInfo+(m_nFillInfo-1);
  496.         ulEnd=pFillInfo->ulOffset+pFillInfo->cb;
  497.     }
  498.     else
  499.     {
  500.         ulEnd=0;
  501.     }
  502.     ULONG cbWritten=0;
  503.     HRESULT hRes=m_pCacheArray->WriteAt(*((ULARGE_INTEGER*) &ulEnd), pv, cb, &cbWritten);
  504.     if (cbWritten>0 && m_nFillInfo==0)
  505.     {
  506.         m_pFillInfo->cb=cbWritten;
  507.         m_pFillInfo->ulOffset=ulEnd;
  508.         m_nFillInfo=1;
  509.         pFillInfo=m_pFillInfo;
  510.     }
  511.     else
  512.     {
  513.         pFillInfo->cb+=cbWritten;
  514.     }
  515.     if (pcbWritten)
  516.     {
  517.         *pcbWritten=cbWritten;
  518.     }
  519.     if (m_ulFillSize && ulEnd>m_ulFillSize)
  520.     {
  521.         m_ulFillSize=ulEnd;
  522.     }
  523.     WRITEFILLINFOUNLOCK;
  524.     PulseEvent(m_hevntNewFillInfo);
  525.     return hRes;
  526. }
  527.  
  528. HRESULT CAsyncByteArray::FillAt(ULARGE_INTEGER ulOffset, void const *pv, ULONG cb, ULONG *pcbWritten) 
  529. {
  530.     if (IsBadWritePtr(this, sizeof(*this))) 
  531.     {
  532.         return E_POINTER;
  533.     }
  534.     if (!m_pCacheArray) 
  535.     {
  536.         return ASTG_E_NOTINITIALIZED;
  537.     }
  538.     ULONG cbWritten=0;
  539.     HRESULT hRes=m_pCacheArray->WriteAt(ulOffset, pv, cb, &cbWritten);
  540.     if (pcbWritten)
  541.     {
  542.         *pcbWritten=cbWritten;
  543.     }
  544.  
  545.     DWORD dwIndex=0;
  546.     DWORDLONG ulEnd=ulOffset.QuadPart+cbWritten;
  547.     BOOL bExtended=FALSE;
  548.     FILLINFO* pFillInfo=NULL;
  549.     WRITEFILLINFOLOCK;
  550.     if (m_ulFillSize && ulEnd>m_ulFillSize)
  551.     {
  552.         m_ulFillSize=ulEnd;
  553.     }
  554.     while (dwIndex<m_nFillInfo)
  555.     {
  556.         pFillInfo=m_pFillInfo+dwIndex;
  557.         // 1.- New block is completely before this block: insert new FillInfo
  558.         if (ulEnd<pFillInfo->ulOffset)
  559.         {
  560.             pFillInfo=NULL;
  561.             if (m_nFillInfo>=m_nFillAlloc)
  562.             {
  563.                 DWORD nNewFillAlloc=m_nFillAlloc+FILLINFOREALLOCSIZE;
  564.                 FILLINFO* pTemp=(FILLINFO*) GlobalReAlloc(m_pFillInfo, sizeof(FILLINFO)*nNewFillAlloc, GMEM_ZEROINIT);
  565.                 if (pTemp)
  566.                 {
  567.                     m_pFillInfo=pTemp;
  568.                     m_nFillInfo=nNewFillAlloc;
  569.                 }
  570.                 else
  571.                 {
  572.                     WRITEFILLINFOUNLOCK;
  573.                     return E_OUTOFMEMORY;
  574.                 }
  575.             }
  576.             pFillInfo=m_pFillInfo+dwIndex;
  577.             memmove((pFillInfo+1), pFillInfo, sizeof(FILLINFO)*(m_nFillInfo-dwIndex));
  578.             pFillInfo->ulOffset=ulOffset.QuadPart;
  579.             pFillInfo->cb=cbWritten;
  580.             m_nFillInfo++;
  581.             break;
  582.         }
  583.         // 2.- New block starts before or with this block:
  584.         //        change ulOffset/cb and check for merge with following block(s)
  585.         if (ulOffset.QuadPart<=pFillInfo->ulOffset)
  586.         {
  587.             pFillInfo->ulOffset=ulOffset.QuadPart;
  588.             if (ulEnd>pFillInfo->ulOffset+pFillInfo->cb)
  589.             {
  590.                 // this block became longer
  591.                 pFillInfo->cb=ulEnd-pFillInfo->ulOffset;
  592.                 bExtended=TRUE; // need to check for possible merge wih following block(s)
  593.             }
  594.             else {
  595.                 // did not change end of this block: done.
  596.                 break;
  597.             }
  598.         }
  599.         // 3.- new block starts within this block
  600.         //        change cb and check for merge with following block(s)
  601.         else if (ulOffset.QuadPart<=pFillInfo->ulOffset+pFillInfo->cb)
  602.         {
  603.             if (ulEnd>pFillInfo->ulOffset+pFillInfo->cb)
  604.             {
  605.                 // this block became longer
  606.                 pFillInfo->cb=ulEnd-pFillInfo->ulOffset;
  607.                 bExtended=TRUE; // need to check for possible merge with following block(s)
  608.             }
  609.             else
  610.             {
  611.                 // did not change end of this block: done.
  612.                 break;
  613.             }
  614.         }
  615.         if (bExtended)
  616.         {
  617.             // if the block was extended, check if can be merged with the following block(s)
  618.             DWORD dwIndex1=dwIndex+1;
  619.             DWORD dwRemoveCount=0; // will remove merge block(s)
  620.             while (dwIndex1<m_nFillInfo)
  621.             {
  622.                 if (ulEnd<m_pFillInfo[dwIndex1].ulOffset)
  623.                 {
  624.                     // new block ends before this block: no more merges
  625.                     break;
  626.                 }
  627.                 else
  628.                 {
  629.                     // merge this block with first modified block
  630.                     dwRemoveCount++; // flag it for removal
  631.                     if (m_pFillInfo[dwIndex1].ulOffset+m_pFillInfo[dwIndex1].cb>ulEnd)
  632.                     {
  633.                         // this block was bigger than the newly written one:
  634.                         //        adjust first modified block
  635.                         pFillInfo->cb=m_pFillInfo[dwIndex1].ulOffset+m_pFillInfo[dwIndex1].cb-pFillInfo->ulOffset;
  636.                         // no more merges since this block did not grow
  637.                         break;
  638.                     }
  639.                 }
  640.                 dwIndex1++;
  641.             }
  642.             if (dwRemoveCount)
  643.             {
  644.                 // remove merged blocks
  645.                 memmove((pFillInfo+1), m_pFillInfo+dwIndex+1+dwRemoveCount, sizeof(FILLINFO)*(m_nFillInfo-dwRemoveCount-dwIndex-1));
  646.                 m_nFillInfo-=dwRemoveCount;
  647.             }
  648.             break;
  649.         }
  650.         dwIndex++;
  651.     }
  652.     if (dwIndex>=m_nFillInfo)
  653.     {
  654.         // new block did not affect any of the existing blocks: append
  655.         pFillInfo=NULL;
  656.         if (m_nFillInfo>=m_nFillAlloc)
  657.         {
  658.             DWORD nNewFillAlloc=m_nFillAlloc+FILLINFOREALLOCSIZE;
  659.             FILLINFO* pTemp=(FILLINFO*) GlobalReAlloc(m_pFillInfo, sizeof(FILLINFO)*nNewFillAlloc, GMEM_ZEROINIT);
  660.             if (pTemp)
  661.             {
  662.                 m_pFillInfo=pTemp;
  663.                 m_nFillInfo=nNewFillAlloc;
  664.             }
  665.             else
  666.             {
  667.                 WRITEFILLINFOUNLOCK;
  668.                 return E_OUTOFMEMORY;
  669.             }
  670.         }
  671.         pFillInfo=m_pFillInfo+dwIndex;
  672.         pFillInfo->ulOffset=ulOffset.QuadPart;
  673.         pFillInfo->cb=cbWritten;
  674.         m_nFillInfo++;
  675.     }
  676.     WRITEFILLINFOUNLOCK;
  677.     PulseEvent(m_hevntNewFillInfo);
  678.     return hRes;
  679. }
  680.  
  681. HRESULT CAsyncByteArray::Terminate(DWORD dwStatus) 
  682. {
  683.     if (IsBadWritePtr(this, sizeof(*this))) 
  684.     {
  685.         return E_POINTER;
  686.     }
  687.     m_bTerminated=TRUE;
  688.     PulseEvent(m_hevntNewFillInfo);
  689.     return S_OK;
  690. }
  691.  
  692. // IConnectionPointContainer methods
  693. HRESULT CAsyncByteArray::EnumConnectionPoints(LPENUMCONNECTIONPOINTS FAR* ppEnum) 
  694. {
  695.     if (IsBadWritePtr(this, sizeof(*this))) 
  696.     {
  697.         return E_POINTER;
  698.     }
  699.     //ASSERT(FALSE);
  700.     return E_NOTIMPL;
  701. }
  702.  
  703. HRESULT CAsyncByteArray::FindConnectionPoint(REFIID iid, LPCONNECTIONPOINT FAR* ppCP) 
  704. {
  705.     if (IsBadWritePtr(this, sizeof(*this))) 
  706.     {
  707.         return E_POINTER;
  708.     }
  709.     if (IsBadWritePtr(ppCP, sizeof(*ppCP))) 
  710.     {
  711.         return E_POINTER;
  712.     }
  713.     if (iid==IID_ILockBytes) 
  714.     {
  715.         if (!m_pLBConnect) 
  716.         {
  717.             try 
  718.             {
  719.                 m_pLBConnect=new CLockBytesConnectionPoint(this);
  720.             } 
  721.             catch(...) 
  722.             {
  723.                 m_pLBConnect=NULL;
  724.             }
  725.         }
  726.         if (!m_pLBConnect) 
  727.         {
  728.             return E_OUTOFMEMORY;
  729.         }
  730.         if (FAILED(m_pLBConnect->QueryInterface(IID_IConnectionPoint, (void**) ppCP))) 
  731.         {
  732.             //ASSERT(FALSE);
  733.             return E_UNEXPECTED;
  734.         }
  735.     }
  736. /*
  737.     else if (iid==IID_IFillLockBytes) 
  738.     {
  739.         if (!m_pFillLBConnect) 
  740.         {
  741.             try 
  742.             {
  743.                 m_pFillLBConnect=new CFillLockBytesConnectionPoint(this);
  744.             }
  745.             catch(...) 
  746.             {
  747.                 m_pFillLBConnect=NULL;
  748.             }
  749.         }
  750.         if (!m_pFillLBConnect) 
  751.         {
  752.             return E_OUTOFMEMORY;
  753.         }
  754.         if (FAILED(m_pFillLBConnect->QueryInterface(IID_IConnectionPoint, *ppCP))) 
  755.         {
  756.             ASSERT(FALSE);
  757.             return E_UNEXPECTED;
  758.         }
  759.     }
  760.     else if (iid==IID_IBindStatusCallBack) 
  761.     {
  762.         if (!m_pBSCConnect) 
  763.         {
  764.             try 
  765.             {
  766.                 m_pBSCConnect=new CBSCConnectionPoint(this);
  767.             } 
  768.             catch(...) 
  769.             {
  770.                 m_pBSCConnect=NULL;
  771.             }
  772.         }
  773.         if (!m_pBSCConnect) 
  774.         {
  775.             return E_OUTOFMEMORY;
  776.         }
  777.         if (FAILED(m_pBSCConnect->QueryInterface(IID_IConnectionPoint, *ppCP))) 
  778.         {
  779.             ASSERT(FALSE);
  780.             return E_UNEXPECTED;
  781.         }
  782.     }
  783. */
  784.     else 
  785.     {
  786.         return CONNECT_E_NOCONNECTION;
  787.     }
  788.     return S_OK;
  789. }
  790.